package Study0;

import com.sun.org.apache.xpath.internal.axes.ReverseAxesWalker;

import java.util.Arrays;

/*数组的进一步探究*/
public class Study06 {
/*二维数组的探究*/
//    二维数组的打印的错误示范
    public static void main (String[] args) {
        int[][] arr = new int[][]{{1,2,3,4,5},{6,7,8,9,10}};
        System.out.println(Arrays.toString(arr)); // 以字符串的形式打印数组 注意这里打印的是 每行的数组被哈希加密的地址
        System.out.println(Arrays.deepToString(arr)); // 以字符串的形式打印二维数组，
        /*for (int tmp:arr) {
            注意二维数组的结构是，两个一维数组构成的，
            这样是错误的
        }*/
        for (int[] tmp:arr) {
            for (int num:tmp) { // 打印两次一维数组的思想
                System.out.print(num+" ");
            }
            System.out.println();
        }

    }
//    二维数组单个一维数组的使用
    public static void main20 (String[] args) {
        int[][] arr = new int[2][];
        arr[0] = new int[3];  // 第一行定义三列
        arr[1] = new int[2];  // 第二行定义两列

       /* int[][] array = new int[][2];
        注意: 在Java当中列数可以省略，可以自动推导出来，但是行数不可以省略，Java无法自动推导出来的
                在C语言当中行数可以省略，可以自动推导出来，但是列数不可以省略，C语言无法自动推导出来的*/
        for (int i = 0; i < arr.length; i++) {  // 二维数组的行的数量
            for (int j = 0; j < arr[i].length; j++) {  // 二维数组中列的数量
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println("****************************");
        for (int[]tmp:arr) {  // 打印行数
            for (int num:tmp) { // 打印列数
                System.out.print(num+" ");
            }
            System.out.println();
        }

    }
//    二维数组的使用for的扩展打印
    public static void main19 (String[] args) {
        int[][] arr = new int[][]{{1,2,3,4,5},{6,7,8,9,10}};
        for (int[] tmp:arr) {    // 注意 二维数组的结构。是由一个一个的一维数组组成的与，C语言中的数组不同的
            for (int num:tmp) {
                System.out.print(num+" ");
            }
            System.out.println();
        }
    }


//    二维数组的各种打印方式,使用两个for循环打印
    public static void main18 (String[] args) {
        int[][] arr = new int[][]{{1,2,3,4,5},{6,7,8,9,10}};
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }


//    二维数组的定义
    public static void main17 (String[] args) {
//        int[][] arr = {1,2,3,4,5,6,7,8,9,10} 在Java中不可以这样，需要括号分割
        int[][] arr1 = {{1,2,3},{4,5,6}};
        int[][] arr2 = new int[][]{{1,2,3},{4,5,6}};
        int[][] arr3 = new int[2][3];
//        int[2][3] arr4 = {{1,2,3},{4,5,6}}; 没有使用new 不可以标注行列的
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(arr1[i][j]+" ");
            }
            System.out.println();
        }

    }


//    Java中的有关数组类的探究
//    找出数组中消失的数值
    public static void main16 (String[] args) {
        int[] arr = new int[]{1,1,2,2,3,3,5,5,9};
        int ret = 0;
        for (int i = 0; i < arr.length; i++) {
            ret ^= arr[i];
            /* ^(异或运算) 特点
            * 1  0^任何数值 == 任何数值本身
            * 2  相同的两个数值 ^(异或运算) == 它本身
            * 3  符合交换律
            * */
        }
        System.out.println("消失的数字为："+ret);
    }


//     一个数组的偶数放到最前面,奇数放到后面
    public static void swap (int[] arr) {
        int left = 0;
        int right = arr.length-1;
        while(left < right) {
            while(left < right && arr[left] % 2 == 0) {
                left++;
            } // left 为奇数时跳出，停止
            while(left < right && arr[right] % 2 !=0) {
                right--;
            } // right 为偶数时，跳出，停止
            if(left < right) { // 奇数，偶数交换位置
                int tmp = arr[left];
                arr[left] = arr[right];
                arr[right] = tmp;
            }
        }

    }
    public static void main15 (String[] args) {
        Study06 swap = new Study06();
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        System.out.println("变换之前："+Arrays.toString(arr));
        Study06.swap(arr);
        System.out.println("变换之后："+Arrays.toString(arr));
    }


// 逆序数组
    public static void reverse (int[] arr) {
        int left = 0;
        int right = arr.length-1;
        while (left < right) {
            int tmp = arr[left];
            arr[left] = arr[right];
            arr[right] = tmp;
            right--;
            left++;
        }
    }
    public static void main14 (String[] args) {
        Study06 reverse = new Study06();
        int[] arr = new int[]{1,2,3,4,5,6};
        System.out.println("逆序之前的数组："+Arrays.toString(arr));
        Study06.reverse(arr);
        System.out.println("逆序之后的数组："+Arrays.toString(arr));

    }


//    冒泡排序的性能较低，Java中内置了更高效的排序算法
    public static void main13 (String[] args) {
        int[] arr = new int[]{12,345,68,87,98,7,5,1};
        Arrays.sort(arr);     // Java 内置的排序算法
        System.out.println(Arrays.toString(arr));   // 以字符串的形式打印数组
    }


//    冒泡排序
    public static void bubbleSort(int[] arr ) {
        for (int i = 0; i < arr.length - 1; i++) {
            boolean flg = false;
            for (int j = 0; j < arr.length-1-i; j++) {
                if(arr[j] > arr[j+1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                    flg = true;
                }
            }
            if(flg == false) {
                break;
            }

        }

    }
    public static void main12 (String[] args) {
        Study06 bubbleSort = new Study06();
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        System.out.println("排序之前："+Arrays.toString(arr));
        Study06.bubbleSort(arr);
        System.out.println("排序之后："+Arrays.toString(arr));
    }




// 检查数组的有序性
    public static boolean isSorted(int[] arr) {           // 判断数组是否是升序
        for (int i = 0; i < arr.length-1; i++) {
            if(arr[i] > arr[i+1]) {
                return false;
            }
        }
        return true;
    }
    public static void main11 (String[] args) {
        Study06 isSorted = new Study06();
    int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
    System.out.println(Study06.isSorted(arr));
}


//    Arrays 有关排序的类
    public static void main10 (String[] args) {
        int[] arr = new int[]{1,2,3,6,8,5,9,4,7,10};
        System.out.println("排序之前"+Arrays.toString(arr));
        Arrays.sort(arr);    // 以升序的方式排序数组
        System.out.println("排序之后"+Arrays.toString(arr));    // 以字符串的形式打印数组
    }



//    修改指定数组中元素的值
    public static void main9 (String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        System.out.println("修改之前的数值："+Arrays.toString(arr));
        Arrays.fill(arr,3,6,10); // 重载：Arrays.fill 修改指定数组范围的元素的值
        System.out.println("修改之后的数值："+Arrays.toString(arr)); // Arrays.toString 以字符串的形式打印数组
//        [fromlndex , tolndex) 是左闭右开的
    }


//    将数组中的所有元素的置为 你想要的数值
    public static void main8 (String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        System.out.println("置之前的数组："+Arrays.toString(arr));
        Arrays.fill(arr,0);          // Arrays.fill 将数组中的全部元素的数值改为你想要的数值
        System.out.println("置之后的数组："+Arrays.toString(arr));  // 以字符串的形式打印数组
    }


//    判断两个数组是否相同
    public static void main7 (String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        int[] ret = Arrays.copyOfRange(arr,0,arr.length); // Arrays.copyOfRange复制指定范围的数组
        boolean bool = Arrays.equals(arr,ret); // Arrays.equals判断两个数组是否相等，返回值为 boolean 类型
        System.out.println(bool);
    }

//    复制数组指定范围的数值
    public static void main6 (String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        int[] ret = Arrays.copyOfRange(arr,5,9); // 复制指定数组范围的元素值
        System.out.println(Arrays.toString(ret));  // 字符串的形式打印数组

    }



//    查找数组中对应数值的类
    public static void main5 (String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        System.out.println(Arrays.binarySearch(arr,5,8,9));   // 规定某个数组的查找范围，
        // 查找某数值，找到返回 下标 ，[fromlndex, tolndex),一般为左闭右开
    }


//    二分查找，大前提是该数组必须要是有序的无论是降序，还是升序
    public static int binarySearch (final int[] arr, final int key) {
        int left = 0;  // 数组的起始位置
        int right = arr.length-1; // 数组有效数值的最后位置
        while(left <= right ) {
            int mid = (left + right) >>> 1;
            if(arr[mid] > key ) {
                right = mid - 1;
            } else if(arr[mid] < key ) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;              // 数组没有下标为 -1 的位置，所以代表没有找到

    }
    public static void main4 (String[] args) {
        Study06 binarySearch = new Study06();
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        int ret = Study06.binarySearch(arr,9);
        System.out.println("下标："+ret);

    }


//    简单查找数组中的数值
    public static int find1 (int[] arr,int key) {
        for (int i = 0; i < arr.length; i++) {
            if(key == arr[i]) {
                return i;
            }
        }
        return -1; // -1 数组没有该位置的下标位置，代表没有这个元素
    }
    public static void main3 (String[] args) {
        Study06 find1 = new Study06();
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        int rct = Study06.find1(arr,0);
        System.out.println("下标："+rct);
    }



//    求数组中值的平均值
    public static double avg(int[] arr) {
        double sum = 0.0;
        /*for (int i = 0; i < arr.length; i++) {
            sum +=arr[i];
        }*/
        for (int num:arr) {
            sum +=num;
        }
        return sum / (double)arr.length;
    }
    public static void main2 (String[] args) {
        Study06 avg = new Study06();
        int[] arr = new int[]{2,2,2,2,2,2,2,2,2,2};
        double mean = Study06.avg(arr);
        System.out.println("平均值是："+mean);
    }



//    求数组中最大的数值
    public static int maxAdd(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(max < arr[i]) {
                max = arr[i];
            }
        }
        return max;
    }
    public static void main1 (String[] args) {
        Study06 maxAdd = new Study06();
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9,10};
        int max = Study06.maxAdd(arr);
        System.out.println("最大值为："+max);
    }
}
